import time
import requests
import re

headers = {'Cookie': '', 'Host': 'www.12306.cn', 'Upgrade-Insecure-Requests': '1',
           'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/70.0.3538.110 Safari/537.36'}
cookie = {'JSESSIONID': '19244E64B10E57EFB354E317CC0DD2C5',
          'BIGipServerotn': '535822858.50210.0000',
          'RAIL_EXPIRATION': '1582333451491',
          'RAIL_DEVICEID': 'McIuEPF2UftrVKz1eNePew8hyOmYixP1IVU1JOTtULuRy2igIY3K71OCqb2YQni1FEkLyWbxf508zd6v91pHbnHRZ2UU0SLJBBsbittDazpLO-ZB7zoirqGyH9ao0cAv_d76BNGKrAVsosQuv0EkQuOczvUHWMcx',
          'BIGipServerpool_passport': '317522442.50215.0000',
          'route': '9036359bb8a8a461c164a04f8f50b252',
          '_jc_save_toStation': '%u4E0A%u6D77%2CSHH',
          '_jc_save_wfdc_flag': 'dc',
          '_jc_save_fromStation': '%u957F%u6C99%2CCSQ',
          '_jc_save_fromDate': '2020-02-19',
          '_jc_save_toDate': '2020-02-19'}


def get_station_name():
    # 爬取12306网站所有车站名称信息
    url = 'https://www.12306.cn/index/script/core/common/station_name_v10026.js'  # 车站信息控件
    r = requests.get(url)
    pattern = '([\u4e00-\u9fa5]+)\|([A-Z]+)'  # 正则匹配规则
    result = re.findall(pattern, r.text)
    station_name = dict(result)  # 所有车站信息，转换为字典
    # print(station_name)
    return station_name


def get_query_url(text, date, from_station, to_station):
    # 构建用于查询列车车次信息的url
    # 参数：日期，出发地，目的地
    # key为车站名称，value为车站代号
    from_station = text[from_station]
    to_station = text[to_station]  # 新的url
    url = ("https://kyfw.12306.cn/otn/leftTicket/query?leftTicketDTO.train_date={}"
           "&leftTicketDTO.from_station={}"
           "&leftTicketDTO.to_station={}"
           "&purpose_codes=ADULT"
           ).format(date, from_station, to_station)
    # print(url)  # 输出测试
    return url


'''
from_station = input('请输入出发站名称：')
to_station = input('请输入到达站名称：')
date = input('请输入出发时间(格式yyyy-mm-dd)：')
'''

text = get_station_name()  # 将车站名称信息保存在text中，键为车站名称，值为车站代号
inverse_text = dict(zip(text.values(), text.keys()))  # 键为车站代号，值为车站名称


def get_info_station(from_station, to_station, date):
    # 获取一天出发站到终点站的相关信息
    # 该函数返回列表，列表包含元素为：'日期', '车次', '出发站代号', '出发站名称', '到达站代号', '到达站名称', '出发时间', '到达时间', '历时',
    # '商务/特等座', '一等座', '二等座', '软卧', '硬卧', '硬座', '无座'
    url = get_query_url(text, date, from_station, to_station)  # 测试：构建用于查询列车车次信息的url
    r = requests.get(url, cookies=cookie)
    all_trains = r.json()['data']['result']  # 获取所有车次信息
#    print('{:7}{:7}{:7}{:7}{:7}{:7}{:7}{:7}{:7}{:7}{:7}{:7}{:7}{:7}{:7}'
#          .format('车次', '出发站代号', '出发站名称', '到达站代号', '到达站名称', '出发时间', '到达时间', '历时',
#                  '商务/特等座', '一等座', '二等座', '软卧', '硬卧', '硬座', '无座'))  # 输出测试
    re_station = list()
    for one_train in all_trains:  # 遍历取出每辆车的信息
        data_list = one_train.split('|')
        # print('data_list:', data_list)  # 测试
        train_number = data_list[3]  # 车次
        from_station_code = data_list[6]  # 出发站代号
        try:
            from_station_name = inverse_text[data_list[6]]  # 出发站名称
        except KeyError:
            from_station_name = data_list[6]
        to_station_code = data_list[7]  # 到达站代号
        try:
            to_station_name = inverse_text[data_list[7]]  # 到达站名称
        except KeyError:
            to_station_name = data_list[7]
        go_time = data_list[8]  # 出发时间
        arrive_time = data_list[9]  # 到达时间
        cost_time = data_list[10]  # 历时
        special_class_seat = data_list[32] or '--'  # 商务/特等座
        first_class_seat = data_list[31] or '--'  # 一等座
        second_class_seat = data_list[30] or '--'  # 二等座
        soft_sleep = data_list[23] or '--'  # 软卧
        hard_sleep = data_list[28] or '--'  # 硬卧
        hard_seat = data_list[29] or '--'  # 硬座
        no_seat = data_list[26] or '--'  # 无座
        train_list = [date, train_number, from_station_code, from_station_name, to_station_code, to_station_name,
                      go_time, arrive_time, cost_time, special_class_seat, first_class_seat, second_class_seat,
                      soft_sleep, hard_sleep, hard_seat, no_seat]
        #    print('{:7}{:7}{:7}{:7}{:7}{:7}{:7}{:7}{:7}{:7}{:7}{:7}{:7}{:7}{:7}'
        #         .format(train_number, from_station_code, from_station_name, to_station_code, to_station_name, go_time,
        #                  arrive_time, cost_time, special_class_seat, first_class_seat, second_class_seat, soft_sleep,
        #                  hard_sleep, hard_seat, no_seat))  # 输出测试
        re_station.append(train_list)
    return re_station


def date_info(date):
    # 用于检查输入日期格式的正确性
    if len(date) == 10:
        date_list = list(map(int, date.split('-')))
        localtime = time.localtime(time.time())  # 获取本地时间
        day_info = [31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31]
        if date_list[0] % 400 == 0 or (date_list[0] % 100 != 0 and date_list[0] % 4 == 0):  # 闰年2月
            day_info[1] = 29
        if localtime.tm_year <= date_list[0] <= localtime.tm_year + 1:  # 年份应该处于今年以及明年之间，超过就无法查询
            if 1 <= date_list[1] <= 12:
                if 1 <= date_list[2] <= day_info[date_list[1] - 1]:
                    return True
    return False


def get_date(date):
    # 用于获取未来五天日期
    date_re = []  # 用于返回信息的列表
    date_list = list(map(int, date.split('-')))
    for i in range(5):
        date_list[2] += 1
        d = '{:4d}-{:02d}-{:02d}'.format(date_list[0], date_list[1], date_list[2])  # 格式化日期，注意前导的0
        if date_info(d):
            date_re.append(d)
        else:
            date_list[1] += 1
            date_list[2] = 1
            if date_info(d):
                date_re.append(d)
            else:
                date_list[0] += 1
                date_list[1] = 1
                date_list[2] = 1
                if date_info(d):
                    date_re.append(d)
    return date_re
